const { Wechaty, UrlLink } = require('wechaty');
const { FileBox } = require('file-box')
const { PuppetPadlocal } = require('wechaty-puppet-padlocal');
const { getMonitorRecord } = require('./utils/index')
const { updateRoomList, getChartRoomList, getMonitorRoomList } = require('./api/roomList')
const { getQuestion, getSlogan } = require('./robotApi/index');
const { messageManager } = require('./messageManager')
const { versionInfo } = require('./config/index')
const { checkVersion } = require('./api/userList')
const { DotaGame } = require('./dotaGame')

const name = 'dota2-bot';
let bot = '';
let timer;
let guessRoomMap = {}
let sloganRoomMap = {}
let messageManagerMap = {}
let lastMessageMap = {}
let messageList = []
let msgIndex = 0
let messageListTimer = null
let isSend = false
let dotaRoomMap = {}

let mRoomList = []

const puppet = new PuppetPadlocal({
  // token: 'puppet_padlocal_0a3e8f46974d4de2816ad15f328b6f84',
  // token: 'puppet_padlocal_b4f3834420384ba2a3caaa0b400ec7c9',
  token:'puppet_padlocal_ea65991553314b389fd3ac9117ed3cd8'
});
bot = new Wechaty({
  name,
  // puppet: 'wechaty-puppet-wechat',
  puppet,
});

// bot = new Wechaty({
//   name,
//   puppet: 'wechaty-puppet-wechat'
// });

// 延时函数，防止检测出类似机器人行为操作
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

//  二维码生成
function onScan(qrcode, status) {
  require('qrcode-terminal').generate(qrcode); // 在console端显示二维码
  const qrcodeImageUrl = [
    'https://wechaty.js.org/qrcode/',
    encodeURIComponent(qrcode),
  ].join('');
  console.log(qrcodeImageUrl);
}

// 登录
async function onLogin(user) {
  console.log(`${user}登录了`);
  await delay(2000)
  recordMonitor()
  handleCheckVersion()
  // 随机出题
  // handleToSendQustion()
}

//登出
function onLogout(user) {
  console.log(`${user} 已经登出`);
  if (timer) {
    console.log('战绩监测关闭')
    clearInterval(timer)
  }
  if (messageListTimer) {
    clearInterval(messageListTimer)
  }
}

// 加群
async function onRoomInvitation(roomInvitation) {
  try {
    console.log(roomInvitation)
    const inviter = await roomInvitation.inviter()
    const name = inviter.name()
    console.log(`邀请人 ${name}`)
    if (name === 'Yet') {
      await roomInvitation.accept()
    }
  } catch (e) {
    console.error(e)
  }
}

// 进群
async function onRoomJoin(room, inviteeList, inviter) {
  const genderList = ['', '男', '女']
  const nameList = inviteeList.map(c => `${c.name()}【${genderList[c.gender()] || '保密'}】`).join(',')
  await room.say(`欢迎新群友${nameList}!请修改你的群昵称:名字-地区-ID,输入help可以查看帮助哦~`)
  console.log(`Room ${await room.topic()} got new member ${nameList}, invited by ${inviter}`)
}

// 退群
async function onRoomLeave(room, leaverList, remover) {
  const nameList = leaverList.map(c => c.name()).join(',')
  await room.say(`${nameList}离开了群聊，祝ta生活愉快吧`)
  console.log(`Room ${await room.topic()} lost member ${nameList}, the remover is: ${remover}`)
}

// 改群名
async function onRoomTopic(room, topic, oldTopic, changer) {
  const rooms = await bot.Room.findAll()
  const res = await updateRoomList({ rooms })
  chartRoomList = (await getChartRoomList()).data
  console.log(`Room ${await room.topic()} topic changed from ${oldTopic} to ${topic} by ${changer.name()}`)
}

// 加好友备注自动拉入深圳群
async function onFriendship(friendship) {
  try {
    console.log(friendship)
    console.log(`received friend event from ${friendship.contact().name()}`)
  } catch (e) {
    console.error(e)
  }
}

// 监听对话
async function onMessage(msg) {
  const contact = msg.talker(); // 发消息人
  const content = msg.text().trim(); // 消息内容
  const room = msg.room(); // 是否是群消息
  const alias = await contact.alias() || await contact.name(); // 发消息人备注
  const isText = msg.type() === bot.Message.Type.Text;
  const isEmoticon = msg.type() === bot.Message.Type.Emoticon
  if (msg.self()) {
    return;
  }

  // 撤回
  if (isText) {
    messageList.push(msg.payload)
  }
  if (room && msg.type() == 13) {
    let name = await contact.name()
    let member = await room.member(name)
    let reg = /<newmsgid>\d+<\/newmsgid>/
    let lastId = reg.exec(msg.payload.text)[0].slice(10, 29)
    let lastMsg = messageList.find(item => {
      return item.id == lastId
    })
    // room.say(`\n【${name}】刚刚撤回了一条消息，回复【查看撤回${lastId}】查看撤回的消息。`)
    room.say(`\n【${name}】刚刚撤回了【${lastMsg.text}】`, member)
  }

  if (room && isText) {
    // 如果是群消息 目前只处理文字消息
    const topic = await room.topic();
    console.log(`群名: ${topic} 发消息人: ${await contact.name()} id: ${await contact.id} 内容: ${content}`);
    // help
    if (['help', '帮助'].includes(content)) {
      const urlLink = new UrlLink({
        description: '这是我的说明书哦',
        title: 'Dota2Bot使用说明',
        url: 'http://help.sanye666.top',
      });
      const message = await room.say(urlLink)
      return
    }
    if(content === '红包'){
      await room.say('二狗 红包')
    }
    // 知识问答
    if (dotaRoomMap[topic] && !dotaRoomMap[topic].isEnd) { // 该群处于知识问答中
      return dotaRoomMap[topic].getAnswer(content.toUpperCase(), contact)
    }
    if (content === '知识问答') {
      if (dotaRoomMap[topic] && !dotaRoomMap[topic].isEnd) {
        return
      }
      dotaRoomMap[topic] = new DotaGame(room)
      return dotaRoomMap[topic].start()
    }

    // if (content.includes('查询年报')) {
    //   const userId = content.replace('查询年报', '').trim()
    //   if (userId) {
    //     const urlLink = new UrlLink({
    //       description: '',
    //       thumbnailUrl: 'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3873039246,733723730&fm=26&gp=0.jpg',
    //       title: '我的2021刀塔年报',
    //       url: `http://dota.sanye666.top/activity/year/${userId}`,
    //     })
    //     return await room.say(urlLink);
    //   } else {
    //     let contact = msg.talker();
    //     // 先查是否绑定过id
    //     const res = await getDotaIdList({
    //       wechatId: contact.id
    //     })
    //     for (const userId of res.data) {
    //       const urlLink = new UrlLink({
    //         description: '',
    //         thumbnailUrl: 'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3873039246,733723730&fm=26&gp=0.jpg',
    //         title: '我的2021刀塔年报',
    //         url: `http://dota.sanye666.top/activity/year/${userId}`,
    //       })
    //       await room.say(urlLink);
    //     }
    //     return
    //   }
    // }
    // if(content.includes('好康')|| content.includes('色图') || content.includes('好看') || content.includes('gkd')){
    //   if(isSend){
    //     let member = await room.member(alias)
    //     room.say('太频繁啦，休息一下',member)
    //     return
    //   }
    //   const urlLink = new UrlLink({
    //     description: '快来看看',
    //     thumbnailUrl: 'https://api.ixxcc.com/img.php?return=img',
    //     title: '我发现了好康的',
    //     url: 'https://api.ixxcc.com/img.php?return=img',
    //   });
    //   const message = await room.say(urlLink)
    //   isSend = true
    //   setTimeout(() => {
    //     isSend = false
    //     room.say('我好了，嘿嘿')
    //     message.recall()
    //   }, 30000);
    //   return
    // }
    // if (content === '圣经') {
    //   const voiceFilePath = "https://dotabot.oss-cn-shenzhen.aliyuncs.com/4.silk"
    //   const voiceLength = 16000; // 需要提供语音长度，单位为毫秒

    //   const fileBox = FileBox.fromUrl(voiceFilePath);
    //   fileBox.mimeType = "audio/silk";
    //   fileBox.metadata = {
    //     voiceLength,
    //   };
    //   room.say(fileBox)
    // }

    if (content === '联系作者') {
      const contactCard = (await bot.Contact.find({ name: "Yet" }))
      await room.say(contactCard);
      return
    }

    if (content === '快来群聊') {
      const rooms = await bot.Room.findAll()
      let rRoomList = rooms.filter(room => {
        return room.payload.topic !== topic
      })
      console.log(rRoomList)
      for (let i = 0; i < rRoomList.length; i++) {
        const room = await bot.Room.find({ topic: rRoomList[i] })
        const message = `[${topic}]想聊天了，输入 加入群聊 即可与该群友好互动！`
        await delay(2000)
        console.log(room)
        if (room) {
          room.say(message)
        }
      }
    }

    if (content === '加入群聊') {
      if (mRoomList.includes(topic)) {
        room.say('该群已在公共群聊中！')
      } else {
        mRoomList.push(topic)
        room.say('加入公共群聊成功！输入 转发+消息内容 即可与公共群聊中的其他群友好互动！')
        let rRoomList = mRoomList.filter(item => { return item !== topic })
        if (rRoomList.length > 0) {
          for (let i = 0; i < rRoomList.length; i++) {
            const room = await bot.Room.find({ topic: rRoomList[i] })
            const message = `[${topic}]已加入公共群聊`
            await delay(2000)
            if (room) {
              room.say(message)
            }
          }
        } else {
          room.say('目前公共群聊中只有咱们群哦，发送 快来群聊 可以提醒其他所有群加入公共群聊！')
        }
      }
      return
    }

    if (content === '退出群聊') {
      if (mRoomList.includes(topic)) {
        mRoomList = mRoomList.filter(room => { return room !== topic })
        room.say('退出公共群聊成功！')
        let rRoomList = mRoomList.filter(item => { return item !== topic })
        if (rRoomList.length > 0) {
          for (let i = 0; i < rRoomList.length; i++) {
            const room = await bot.Room.find({ topic: rRoomList[i] })
            const message = `[${topic}]已退出公共群聊`
            await delay(2000)
            if (room) {
              room.say(message)
            }
          }
        }
      } else {
        room.say('该群未在公共群聊中！')
      }
      return
    }

    if (content === '群聊列表') {
      if (mRoomList.length > 0) {
        let roomListStr = mRoomList.join('\n')
        room.say(`公共群聊列表\n${roomListStr}`)
      } else {
        room.say('公共群聊中未加入任何群！')
      }
      return
    }


    // 消息互转
    if (content.startsWith('转发')) {
      let _content = content.replace('转发', '')
      if (_content && mRoomList.includes(topic)) {
        let rRoomList = mRoomList.filter(item => { return item !== topic })
        if (rRoomList.length === 0) {
          room.say('公共群聊中暂无其他群')
        } else {
          for (let i = 0; i < rRoomList.length; i++) {
            const room = await bot.Room.find({ topic: rRoomList[i] })
            const message = `[${await contact.name()}@${topic}]: ${_content}`
            await delay(2000)
            if (room) {
              room.say(message)
            }
          }
        }
      }
      return
    }

    // 复读
    if (lastMessageMap[topic]) {
      let message;
      if (isEmoticon) {
        message = await msg.toFileBox()
        if (lastMessageMap[topic].lastMessageType === 'Emoticon') {
          if (lastMessageMap[topic].lastMessage._metadata.md5 == message._metadata.md5 && (!lastMessageMap[topic].lastRereadMesasge || lastMessageMap[topic].lastRereadMesasge._metadata.md5 !== message._metadata.md5)) { // 当前消息等于上一条消息  而且机器人没有幅度过
            room.say(message)
            lastMessageMap[topic].lastRereadMesasge = message
          }
        }
      } else {
        message = content
        if (lastMessageMap[topic].lastMessageType === 'Text') {
          if (lastMessageMap[topic].lastMessage == message && lastMessageMap[topic].lastRereadMesasge !== message) { // 当前消息等于上一条消息  而且机器人没有幅度过
            room.say(message)
            lastMessageMap[topic].lastRereadMesasge = message
          }
        }
      }
      lastMessageMap[topic].lastMessage = message
      lastMessageMap[topic].lastMessageType = isEmoticon ? 'Emoticon' : 'Text'
    } else {
      lastMessageMap[topic] = {
        lastMessage: content,
        lastMessageType: isEmoticon ? 'Emoticon' : 'Text',
        lastRereadMesasge: null
      }
    }

    // 猜谜
    // if (guessRoomMap[topic] && !guessRoomMap[topic].isEnd) { // 该群处于猜谜中
    //   const name = await contact.name()
    //   guessRoomMap[topic].getAnswer(content, name)
    //   return
    // }
    // if (content === '猜谜语') {
    //   guessRoomMap[topic] = new guessGame(room)
    //   guessRoomMap[topic].start()
    //   return
    // }

    // 猜广告
    // if (sloganRoomMap[topic] && !sloganRoomMap[topic].isEnd) { // 该群处于猜谜中
    //   const name = await contact.name()
    //   let answer = content.includes('@Dota2Bot') ? content.replace('@Dota2Bot', '').trim() : content.trim()
    //   sloganRoomMap[topic].getAnswer(answer, name)
    //   return
    // }
    // if (content === '猜广告') {
    //   sloganRoomMap[topic] = new sloganGame(room)
    //   sloganRoomMap[topic].start()
    //   return
    // }

    if (!messageManagerMap[topic]) {
      messageManagerMap[topic] = new messageManager()
      await messageManagerMap[topic].init()
    }
    messageManagerMap[topic].messageHandler(msg)

  } else if (isText) {
    // 如果非群消息 目前只处理文字消息
    console.log(`发消息人: ${alias} 消息内容: ${content}`);
    if (content.includes('深圳') || content.includes('猛犸') || content.includes('max') || content.includes('群')) {
      const room = await bot.Room.find({ topic: '深圳刀友群' })
      await room.add(contact)
      return
    }
    if (content === '更新配置') {
      try {
        const rooms = await bot.Room.findAll()
        const res = await updateRoomList({ rooms })
        chartRoomList = (await getChartRoomList()).data
        console.log(res)
        contact.say(res.data)
      } catch (error) {
        contact.say('更新失败!')
      }
      return
    }
    if (content.includes('全体消息')) {
      const message = content.slice(4, content.length)
      sayAllRoom(message)
      return
    }
    if (content === '版本更新') {
      handleCheckVersion()
      return
    }
    if (alias === 'Yet') {
      const voiceFilePath = "https://dotabot.oss-cn-shenzhen.aliyuncs.com/4.silk"
      const voiceLength = 16000; // 需要提供语音长度，单位为毫秒

      const fileBox = FileBox.fromUrl(voiceFilePath);
      fileBox.mimeType = "audio/silk";
      fileBox.metadata = {
        voiceLength,
      };
      // const imageFileUrl = "https://dotabot.oss-cn-shenzhen.aliyuncs.com/1.png";
      // const fileBox = FileBox.fromUrl(imageFileUrl);
      const room = await bot.Room.find({ topic: content })
      // await room.say('富婆 饿饿 饭饭')
      // await delay(1000)
      await room.say(fileBox)
    }
  }
}

function recordMonitor() {
  recordMonitorStart()
  const hours = new Date().getHours()
  const timeCount = [2, 3, 4, 5, 6].includes(hours) ? 1800000 : 600000 // 2:00 ~ 6:59 查询间隔为30分钟 其他时间段 10分钟
  timer = setInterval(() => {
    recordMonitorStart()
    if ([2, 3, 4, 5, 6].includes(new Date().getHours())) {
      if (timeCount === 600000) {
        clearInterval(timer)
        recordMonitor()
      }
    } else {
      if (timeCount === 1800000) {
        clearInterval(timer)
        recordMonitor()
      }
    }
  }, timeCount)
}

async function recordMonitorStart() {
  try {
    const res = await getMonitorRoomList()
    const monitorRoomList = res.data
    for (let i = 0; i < monitorRoomList.length; i++) {
      if (monitorRoomList[i].monitorMemberList) {
        for (let j = 0; j < monitorRoomList[i].monitorMemberList.length; j++) {
          await delay(4000)
          const res = await getMonitorRecord(monitorRoomList[i].monitorMemberList[j])
          if (res.msg) {
            const room = await bot.Room.find({ topic: monitorRoomList[i].topic })
            await room.say(res.msg)
          }
          if (res.match_id) {
            const urlLink = new UrlLink({
              description: '这场比赛你怎么看',
              thumbnailUrl: 'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3873039246,733723730&fm=26&gp=0.jpg',
              title: '比赛详情',
              url: `http://dota.sanye666.top/match/${res.match_id}?redirect=Home`,
            })
            const room = await bot.Room.find({ topic: monitorRoomList[i].topic })
            await room.say(urlLink);
          }
        }
      }
    }
  } catch (error) {
    console.log(error)
  }
}

class guessGame {
  constructor(room, questionCount = 5) {
    this.room = room
    this.questionCount = questionCount
    this.questionList = []
    this.questionIndex = 0
    this.isEnd = false
    this.countTimer = null
    this.questionTimer = null
    this.answerTimer = null
    this.tipsTimer = null
  }

  async start() { // 开始答题
    this.isEnd = false
    this.questionList = await this.getQuestion()
    await this.room.say('开始猜谜语喽！每题限时1分钟，总共5题，仔细看哦！\n（游戏中小壕不回复消息哦）')
    console.log(this.questionList)
    this.setQusetion()
  }

  next() { // 下一题
    this.questionIndex++
    this.clearTimer()
    if (this.questionIndex < this.questionList.length) {
      this.setQusetion()
    } else {
      this.end()
    }
  }

  end() { // 答题结束
    this.timer = null;
    const guessPersonList = []
    for (let index = 0; index < this.questionList.length; index++) {
      if (this.questionList[index].guessPerson) {
        if (guessPersonList.length === 0) {
          guessPersonList.push({
            [this.questionList[index].guessPerson]: 1
          })
        } else {
          guessPersonList.forEach(item => {
            if (item[this.questionList[index].guessPerson]) {
              item[this.questionList[index].guessPerson] = item[this.questionList[index].guessPerson] + 1
            } else {
              guessPersonList.push({
                [this.questionList[index].guessPerson]: 1
              })
            }
          })
        }
      }
    }
    let result = `猜谜语结束，现在公布成绩`
    guessPersonList.forEach(item => {
      result += `\n${Object.keys(item)[0]}答对了${Object.values(item)[0]}道题目`
    })
    setTimeout(() => {
      this.room.say(result)
    }, 1000);
    this.questionList = []
    this.questionIndex = 0
    this.isEnd = true
  }

  // 获取题目
  async getQuestion() {
    return new Promise(async (resolve, reject) => {
      try {
        const list = []
        for (let index = 1; index <= this.questionCount; index++) {
          const res = (await getQuestion()).newslist[0]
          list.push({
            question: res.quest,
            answer: res.answer,
            guessPerson: null
          })
        }
        resolve(list)
      } catch (error) {
        reject(error)
      }
    })
  }

  // 提问
  setQusetion() {
    this.countTimer = setTimeout(() => {
      this.room.say(`第${this.questionIndex + 1}题：每题限时1分钟`)
    }, 1000);
    this.questionTimer = setTimeout(async () => {
      this.room.say(this.questionList[this.questionIndex].question)
    }, 2000);
    this.tipsTimer = setTimeout(() => {
      if (this.questionList[this.questionIndex].answer.length > 1) {
        let answerTip = '◼️'.repeat(this.questionList[this.questionIndex].answer.length - 1) + this.questionList[this.questionIndex].answer.slice(this.questionList[this.questionIndex].answer.length - 1)
        this.room.say(`💡还剩30秒！提示：${answerTip}`)
      }
    }, 30000);
    this.answerTimer = setTimeout(() => {
      this.room.say(`[旺柴]时间到！很遗憾，没有人能够猜对。谜底就是【${this.questionList[this.questionIndex].answer}】`)
      this.next()
    }, 60000)
  }

  clearTimer() {
    clearTimeout(this.countTimer)
    clearTimeout(this.questionTimer)
    clearTimeout(this.tipsTimer)
    clearTimeout(this.answerTimer)
  }

  // 答题
  async getAnswer(answer, name) {
    if (answer == this.questionList[this.questionIndex].answer) {
      const member = await this.room.member(name)
      await this.room.say(`[鼓掌]恭喜猜对了！答案就是【${answer}】`, member)
      this.questionList[this.questionIndex].guessPerson = name
      this.next()
    }
  }
}

class sloganGame {
  constructor(room) {
    this.room = room
    this.slogan = {}
    this.isEnd = false
    this.tipsTimer = null
    this.answerTimer = null
  }

  async start() { // 开始答题
    this.isEnd = false
    this.slogan = (await getSlogan()).newslist[0]
    await this.room.say(this.slogan.content)
    this.tipsTimer = setTimeout(() => {
      this.room.say(`💡还剩30秒！`)
      this.getTips()
    }, 30000)
    this.answerTimer = setTimeout(() => {
      this.room.say(`[旺柴]时间到！很遗憾，没有人能够猜对。答案就是【${this.slogan.answer}】`)
      this.end()
    }, 60000)
  }

  end() {
    clearTimeout(this.tipsTimer)
    clearTimeout(this.answerTimer)
    this.isEnd = true
  }

  getTips() {
    if (this.slogan.answer.length > 1) {
      let answerTip = '◼️'.repeat(this.slogan.answer.length - 1) + this.slogan.answer.slice(this.slogan.answer.length - 1)
      this.room.say(`提示：${answerTip}`)
    } else {
      this.room.say(`只有一个字哦`)
    }
  }

  // 答题
  async getAnswer(answer, name) {
    if (answer == this.slogan.answer) {
      const member = await this.room.member(name)
      await this.room.say(`[鼓掌]恭喜猜对了！答案就是【${answer}】`, member)
      this.end()
    } else if (answer == '提示') {
      this.getTips()
    }
  }

}

// 检查版本
async function handleCheckVersion() {
  const versionRes = await checkVersion(versionInfo)
  if (versionRes.code == 200) {
    const chartRoomRes = await getChartRoomList()
    if (chartRoomRes.code == 200) {
      const chartRoomList = chartRoomRes.data
      for (let index = 0; index < chartRoomList.length; index++) {
        await delay(5000)
        const room = await bot.Room.find({ topic: chartRoomList[index] })
        await room.say(versionRes.data.updateContent)
      }
    }
  }
}

// say 
async function sayAllRoom(word) {
  const chartRoomRes = await getChartRoomList()
  if (chartRoomRes.code == 200) {
    const chartRoomList = chartRoomRes.data
    for (let index = 0; index < chartRoomList.length; index++) {
      await delay(5000)
      const room = await bot.Room.find({ topic: chartRoomList[index] })
      if (room) {
        await room.say(word)
      }
    }
  }
}

// 10分钟随机提问
function handleToSendQustion() {
  setInterval(async () => {
    const chartRoomRes = await getChartRoomList()
    if (chartRoomRes.code == 200) {
      const chartRoomList = chartRoomRes.data
      for (let index = 0; index < chartRoomList.length; index++) {
        await delay(5000)
        const room = await bot.Room.find({ topic: chartRoomList[index] })
        if (room) {
          dotaRoomMap[topic] = new DotaGame(room)
          dotaRoomMap[topic].start()
        }
      }
    }
  }, 3600000)
}

bot.on('scan', onScan)
bot.on('login', onLogin)
bot.on('logout', onLogout)
bot.on('message', onMessage)
bot.on('room-invite', onRoomInvitation)
bot.on('room-join', onRoomJoin)
bot.on('room-leave', onRoomLeave)
bot.on('room-topic', onRoomTopic)
bot.on('friendship', onFriendship)
bot
  .start()
